<template>
  <div class="box">
    <div class="box-right">
      <!-- <div class="box-right-nav">
        <input type="text" placeholder="搜索..." />
      </div> -->
      <div class="box-right-title">
        <h2>图书管理</h2>
        <p>管理图书信息、分类统计</p>
      </div>
      <div class="box-right-main">
        <div class="top">
          <div class="top-left">
            <el-button type="primary" @click="add" v-if="isAdmin"
              >新增图书</el-button
            >
          </div>
          <div class="top-right">
            <!-- 一级分类选择器 -->
            <el-select
              v-model="selectedCategory"
              placeholder="主分类"
              clearable
              style="width: 150px; margin-right: 10px"
              @change="handleMainCategoryChange"
            >
              <el-option
                v-for="category in categories"
                :key="category.id"
                :label="category.name"
                :value="category.id"
              />
            </el-select>

            <!-- 二级分类选择器 -->
            <el-select
              v-model="selectedSubCategory"
              placeholder="子分类"
              :disabled="!selectedCategory"
              style="width: 150px"
              @change="handleSubCategoryChange"
            >
              <el-option
                v-for="sub in getSubCategories()"
                :key="sub.id"
                :label="sub.name"
                :value="sub.id"
              />
            </el-select>
          </div>
        </div>
        <div class="main">
          <el-table
            height="500"
            :data="tableData"
            v-loading="loading"
            :default-sort="{ prop: 'id', order: 'ascending' }"
          >
            <el-table-column prop="coverUrl" label="封面" width="90">
              <template #default="{ row }">
                <img
                  :src="row.coverUrl"
                  style="width: 60px; height: 80px; object-fit: cover"
                />
                <!-- <span v-else-if="row.coverUrl && !isHttpImage(row.coverUrl)">
                  本地封面
                </span>
                <el-button v-else size="mini" @click="handleGetCover(row.id)">
                  获取封面
                </el-button> -->
              </template>
            </el-table-column>
            <el-table-column prop="id" label="图书标识符" width="140">
            </el-table-column>
            <el-table-column prop="isbn" label="ISBN" width="120">
            </el-table-column>
            <el-table-column prop="categoryid" label="分类id" width="140">
            </el-table-column>
            <el-table-column prop="title" label="书名" width="130">
            </el-table-column>
            <el-table-column prop="author" label="作者" width="140">
            </el-table-column>
            <el-table-column prop="stock" label="库存" width="90">
            </el-table-column>
            <el-table-column label="操作" width="180" fixed="right">
              <template #default="{ row }">
                <el-button
                  size="mini"
                  type="primary"
                  @click="handleEdit(row)"
                  icon="el-icon-edit"
                  v-if="isAdmin"
                  >修改</el-button
                >
                <el-button
                  size="mini"
                  type="danger"
                  @click="handleDelete(row.id)"
                  icon="el-icon-delete"
                  v-if="isAdmin"
                  >删除</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </div>
        <div class="button">
          <div class="chart-box">
            <h3>图书分类树状图</h3>
            <div id="treeChart" style="width: 100%; height: 340px"></div>
          </div>
          <div class="chart-box">
            <h3>各类图书数量统计</h3>
            <div id="barChart" style="width: 100%; height: 340px"></div>
          </div>
        </div>
      </div>
    </div>
    <!-- // 新增图书对话框 -->
    <el-dialog title="新增图书" :visible.sync="dialogVisible" width="50%">
      <el-form :model="bookForm" :rules="rules" ref="bookForm">
        <el-form-item label="书名" prop="title">
          <el-input v-model="bookForm.title"></el-input>
        </el-form-item>
        <el-form-item label="作者" prop="author">
          <el-input v-model="bookForm.author"></el-input>
        </el-form-item>
        <el-form-item label="ISBN" prop="isbn">
          <el-input v-model="bookForm.isbn"></el-input>
        </el-form-item>
        <el-form-item label="分类ID" prop="categoryid">
          <el-input v-model="bookForm.categoryid"></el-input>
        </el-form-item>
        <el-form-item label="封面" prop="cover">
          <el-upload
            class="avatar-uploader"
            :action="''"
            :show-file-list="false"
            :auto-upload="false"
            :on-change="handleChange"
          >
            <img
              v-if="bookForm.coverUrl"
              :src="bookForm.coverUrl"
              class="avatar"
            />
            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
          </el-upload>
        </el-form-item>
        <el-form-item label="库存" prop="stock">
          <el-input-number v-model="bookForm.stock" :min="0"></el-input-number>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="submitForm">提交</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<!-- <script src="../js/echarts.min.js"></script> -->
<script>
import * as echarts from "echarts";
import { requestBookCategory } from "../util/request.js";
import { addBook } from "../util/getAddBook.js";
import { searchBooks } from "../util/findBook.js";
import { updateBook, updateBookCover } from "../util/upBook.js";
import { deleteBook } from "../util/deleteBook.js";
import { getUser } from "../Service/user-managament.js";
import { getUserId } from "@/Service/huo-qu.js";
import { huoqubook } from "@/util/huoqubook.js";
import { getServerFileURL } from "../util/request.js";
export default {
  data() {
    return {
      treeData: [], //树状图数据
      barData: [], //柱状图数据
      input: "", //搜索框数据
      tableData: [], //表格数据
      chartTree: null, // 声明树状实例
      chartBar: null, //声明柱状实例
      dialogVisible: false, //新增图书对话框显示状态
      isEditMode: false, //是否为编辑模式
      currentBookId: null,
      userAvatarFile: "", //当前编辑图书的id
      // 新增图书表单
      bookForm: {
        title: "",
        author: "",
        isbn: "",
        categoryid: "",
        coverUrl: "",
        coverFile: null,
        stock: 0,
      }, //新增图书表单验证规则
      rules: {
        title: [{ required: true, message: "请输入书名", trigger: "blur" }],
        author: [{ required: true, message: "请输入作者", trigger: "blur" }],
        isbn: [{ required: true, message: "请输入ISBN", trigger: "blur" }],
        coverUrl: [
          { required: false, message: "请上传封面图片", trigger: "change" },
        ],
      },
      selectedCategory: null, // 一级分类
      selectedSubCategory: null, // 二级分类
      categories: [], // 从 requestBookCategory 获取
      loading: false, //显示加载动画
      currentUser: null, //当前用户
      isAdmin: false, //是否为管理员
      currentUserId: null,
    };
  },
  methods: {
    // 上传文件前处理
    handleFileChange(file, fileList) {
      // 确保只保留一个文件
      if (fileList.length > 1) {
        fileList.splice(0, 1);
      }
      // this.beforeUpload(file);
    },
    // 上传文件
    // beforeUpload(file) {
    //   const allowedTypes = ["image/jpeg", "image/png", "image/jpg"];
    //   const isImage = allowedTypes.includes(file.type);
    //   const isLt2M = file.size / 1024 / 1024 < 2;

    //   if (!isImage) {
    //     this.$message.error("只能上传 JPG/PNG 格式图片!");
    //     return false;
    //   }
    //   if (!isLt2M) {
    //     this.$message.error("图片大小不能超过 2MB!");
    //     return false;
    //   }

    //   // 创建预览
    //   this.bookForm.coverUrl = URL.createObjectURL(file);
    //   this.bookForm.coverFile = file;

    //   // 返回 false 手动控制上传
    //   return false;
    // },

    handleAvatarSuccess(response, file) {
      // 使用本地预览 URL 显示图片
      this.bookForm.coverUrl = URL.createObjectURL(file);
      this.userAvatarFile = file; // 保存文件对象供后续提交使用
    },
    handleChange(file) {
      this.userAvatarFile = file.raw; // 保存原始 File 对象
      this.bookForm.coverUrl = URL.createObjectURL(file.raw); // 预览
    },
    customUpload() {
      // 拦截上传行为，由 saveSettings 控制统一提交
      return false;
    }, // 上传成功处理
    handleUploadSuccess(res, file) {
      if (res.code === 200) {
        this.bookForm.coverUrl = URL.createObjectURL(file.raw);
        this.$message.success("上传成功");
      } else {
        this.$message.error(res.message || "上传失败");
      }
    },
    // 上传失败处理
    handleUploadError(err) {
      console.error("上传失败:", err);
      this.$message.error("上传失败");
    },
    // 获取初始图书数据
    async loadInitialBooks() {
      this.loading = true;
      try {
        console.log("正在获取初始图书数据...");
        const res = await huoqubook(1);
        console.log("获取到的图书数据:", res); // 默认加载第一页
        if (res.code === 200) {
          this.tableData = res.data || [];
          await this.validateBooksCoverUrl();
          console.log("表格数据已更新:", this.tableData); // 添加日志
        } else {
          console.error("获取图书失败:", res.message);
          this.$message.error(res.message || "获取图书失败");
        }
      } catch (error) {
        console.error("初始化加载图书失败:", error);
        this.$message.error("初始化加载图书失败");
      } finally {
        this.loading = false;
      }
    },
    async validateBooksCoverUrl() {
      this.tableData = this.tableData.map((book) => {
        if (!book.coverUrl.startsWith("http")) {
          getServerFileURL(`/book/${book.id}/cover`).then((url) => {
            book.coverUrl = url;
          });
        }
        return book;
      });
    },
    // 获取用户信息并判断权限
    async fetchUserAndCheckAdmin() {
      try {
        // 获取当前用户ID
        console.log("获取当前用户ID...");
        this.currentUserId = await getUser(getUserId());
        if (!this.currentUserId) {
          console.warn("未获取到用户ID");
          this.isAdmin = false;
          return;
        }

        // 根据角色字段判断管理员权限
        this.isAdmin = this.currentUserId.isAdmin;

        console.log(
          `用户[${
            this.currentUserId.username || this.currentUserId.id
          }]权限状态: ${this.isAdmin ? "管理员" : "普通用户"}`
        );
      } catch (error) {
        console.error("获取用户信息失败:", error);
        this.isAdmin = false;
        this.$message.error("获取用户权限失败");
      }
    },
    //修改图书
    handleEdit(row) {
      this.operation = "edit";
      this.dialogVisible = true;
      this.bookForm = {
        ...row,
        stock: parseInt(row.stock), // 确保数字类型
        coverUrl: row.coverUrl || "", // 确保封面URL正确处理
        coverFile: null, // 重置文件对象
      };
      this.isEditMode = true;
      this.currentBookId = row.id;
    },

    // 删除图书
    handleDelete(bookId) {
      // 添加bookId参数
      this.$confirm("确定要删除该图书吗?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(async () => {
          try {
            await deleteBook(bookId); // 调用删除API
            this.$message.success("删除成功");

            // 直接从tableData中移除被删除的图书
            this.tableData = this.tableData.filter(
              (item) => item.id !== bookId
            );

            // 如果需要重新加载数据保持同步（可选）
            // this.handleCategoryChange(
            //   this.selectedSubCategory || this.selectedCategory
            // );
          } catch (error) {
            this.$message.error("删除失败: " + error.message);
          }
        })
        .catch(() => {
          this.$message.info("已取消删除");
        });
    },

    // 获取二级分类
    getSubCategories() {
      if (!this.selectedCategory) return [];
      const category = this.categories.find(
        (c) => c.id === this.selectedCategory
      );
      return category?.children || [];
    },
    // 一级分类改变时处理
    async handleMainCategoryChange(val) {
      this.selectedSubCategory = null;
      if (val) {
        await this.loadBooksByCategory(val, true); // 新增参数表示加载主分类
      } else {
        this.tableData = [];
      }
    },

    // 二级分类改变时处理
    handleSubCategoryChange(val) {
      if (val) {
        this.loadBooksByCategory(val); // 加载特定子分类的图书
      }
    },

    // 通用的分类图书加载方法
    async loadBooksByCategory(categoryId, isMainCategory = false) {
      this.loading = true;
      try {
        let res;
        if (isMainCategory) {
          // 如果是主分类，获取该分类及其所有子分类的图书
          const mainCategory = this.categories.find((c) => c.id === categoryId);
          const allSubCategoryIds =
            mainCategory?.children?.map((sub) => sub.id) || [];
          const allCategoryIds = [categoryId, ...allSubCategoryIds];

          // 获取所有相关分类的图书
          const promises = allCategoryIds.map((id) => searchBooks("", id));
          const results = await Promise.all(promises);
          res = {
            data: results.flatMap((r) => r.data || []),
            code: 200,
          };
        } else {
          // 如果是子分类，正常查询
          res = await searchBooks("", categoryId);
        }

        if (res.code === 200) {
          this.tableData = (res.data || []).map((book) => {
            if (!book.coverUrl) {
              return { ...book, coverUrl: "" };
            }
            return book;
          });
        }
      } catch (error) {
        console.error("加载图书失败:", error);
        this.$message.error("加载图书失败");
      } finally {
        this.loading = false;
      }
      await this.validateBooksCoverUrl();
      console.log(this.tableData);
    },

    // 搜索图书
    async searchBooks() {
      if (!this.searchQuery.trim()) {
        this.$message.warning("请输入搜索内容");
        return;
      }

      this.loading = true;
      try {
        const res = await searchBooks(this.searchQuery, this.selectedCategory);
        if (res.code === 200) {
          this.tableData = res.data;
          if (res.data.length === 0) {
            this.$message.info("未找到匹配的图书");
          }
        } else {
          this.$message.error(res.message || "搜索失败");
        }
      } catch (error) {
        this.$message.error("搜索出错: " + error.message);
      } finally {
        this.loading = false;
      }
    },

    // 获取分类数据
    async fetchCategories() {
      try {
        const res = await requestBookCategory();
        if (res.code === 200) {
          this.categories = res.data;
        }
      } catch (error) {
        console.error("获取分类失败:", error);
      }
    },
    // 添加图书
    add() {
      this.operation = "add";
      this.dialogVisible = true; //打开addbook对话框
    },
    //提交表单
    async submitForm() {
      let res;
      if (this.operation === "add") {
        res = await addBook(this.bookForm);
        if (res.code != 200) {
          this.$message.error(res.message);
        } else {
          this.$message.success("添加成功");
        }
        res = await updateBookCover(this.bookForm.id, this.userAvatarFile);
        if (res.code != 200) {
          this.$message.error(res.message);
        } else {
          this.$message.success("添加封面成功");
        }
      } else {
        res = await updateBook(this.bookForm);
        if (res.code != 200) {
          this.$message.error(res.message);
        } else {
          this.$message.success("修改成功");
        }
        res = await updateBookCover(this.bookForm.id, this.userAvatarFile);
        if (res.code != 200) {
          this.$message.error(res.message);
        } else {
          this.$message.success("修改封面成功");
          console.log("修改封面成功");
        }
      }
      this.dialogVisible = false;

      // this.$refs.bookForm.validate(async (valid) => {
      //   if (valid) {
      //     try {
      //       //添加封面
      //       if (this.bookForm.coverFile) {
      //         const formData = new FormData();
      //         formData.append("cover", this.bookForm.coverFile);
      //         for (let [key, value] of formData.entries()) {
      //           console.log(key, value);
      //         }

      //         // 上传封面
      //         const uploadRes = await obtainBookCover(
      //           this.isEditMode ? this.currentBookId : "temp",
      //           formData
      //         );
      //         console.log("上传结果:", uploadRes);
      //         if (uploadRes || uploadRes.code !== 200) {
      //           throw new Error(uploadRes.message || "封面上传失败");
      //         }
      //         if (!uploadRes.data?.url) {
      //           throw new Error("服务器未返回有效的封面URL");
      //         }
      //         this.bookForm.coverUrl = uploadRes.data.url;
      //       }

      //       if (this.isEditMode) {
      //         // 编辑模式 - 调用更新API
      //         const updatedBook = await updateBook({
      //           ...this.bookForm,
      //           id: this.currentBookId,
      //         });

      //         this.$message.success("修改成功");

      //         // 更新本地数据
      //         const index = this.tableData.findIndex(
      //           (item) => item.id === this.currentBookId
      //         );
      //         if (index !== -1) {
      //           this.tableData.splice(index, 1, updatedBook);
      //         }
      //       } else {
      //         // 新增模式
      //         await addBook(this.bookForm);
      //         this.$message.success("添加成功");
      //         if (this.selectedSubCategory || this.selectedCategory) {
      //           await this.loadBooksByCategory(
      //             this.selectedSubCategory || this.selectedCategory,
      //             !!this.selectedSubCategory
      //           );
      //         }
      //       }
      //       this.dialogVisible = false;
      //       this.resetForm();
      //     } catch (error) {
      //       console.error("表单提交失败详情:", {
      //         error: error.response?.data || error.message,
      //         config: error.config,
      //       });
      //       this.$message.error(error.message);
      //     } finally {
      //       this.loading = false;
      //     }
      //   }
      // });
    },
    // 重置表单
    resetForm() {
      this.bookForm = {
        title: "",
        author: "",
        isbn: "",
        categoryid: "",
        coverUrl: "",
        coverFile: null,
        stock: 0,
      };
    },

    isHttpImage(url) {
      return url?.startsWith("http://") || url?.startsWith("https://");
    },

    // 新增树状图数据生成方法
    getTreeData() {
      return {
        name: "图书分类",
        children: this.treeData,
      };
    },

    // 新增柱状图数据生成方法
    countCategoryBooks(categories) {
      let categoryBookNumber = [];
      categories.forEach((category) => {
        let bookCount = 0;
        category.children.forEach((subcategory) => {
          const count = subcategory.books?.length;
          console.log(count);
          if (!isNaN(count)) {
            bookCount += count;
          }
        });
        categoryBookNumber.push({
          name: category.name,
          bookCount: bookCount,
        });
      });
      return categoryBookNumber;
    },
  },

  async mounted() {
    // 检查用户是否为管理员
    await this.fetchUserAndCheckAdmin();
    //获取分类
    await this.fetchCategories();
    //获取图书
    await this.loadInitialBooks();
    //获取树状图数据
    let res = await requestBookCategory();
    if (res.code === 200) {
      this.treeData = res.data;
    } else {
      console.log(res.message);
    }

    // 获取柱状图数据
    const categoryBookCounts = this.countCategoryBooks(res.data);

    this.$nextTick(() => {
      // 初始化树状图
      this.chartTree = echarts.init(document.getElementById("treeChart"));

      // 树状图配置
      const treeOption = {
        tooltip: {
          trigger: "item",
          triggerOn: "mousemove",
          backgroundColor: "rgba(255, 255, 255, 0.9)",
          textStyle: { color: "#333" },
          formatter: (params) => {
            return `分类: ${params.name}<br>书籍数量: ${params.value || 0}`;
          },
        },
        series: [
          {
            type: "tree",
            data: [this.getTreeData()],
            top: "5%",
            left: "8%",
            bottom: "5%",
            right: "20%",
            orient: "LR", // 从左到右布局
            layout: "orthogonal", // 正交布局（保持节点对齐）
            symbol: "circle",
            symbolSize: 8,
            initialTreeDepth: 2,
            label: {
              position: "right",
              verticalAlign: "middle",
              align: "left",
              fontSize: 12,
              color: "#333",
              backgroundColor: "rgba(255,255,255,0.8)", // 标签背景
              padding: [2, 5], // 标签内边距
              borderRadius: 3, // 标签圆角
            },
            leaves: {
              label: {
                position: "right",
                verticalAlign: "middle",
                align: "left",
              },
            },
            itemStyle: {
              color: "#4080FF",
              borderColor: "#333",
              borderWidth: 1,
            },
            lineStyle: {
              color: "#999", // 连接线颜色
              width: 1.5, // 连接线粗细
              curveness: 0.5, // 连接线弯曲度（0-1）
              type: "curve", // 曲线类型
            },
            emphasis: {
              focus: "descendant",
              blurScope: "ancestor",
              label: {
                fontSize: 14,
              },
              itemStyle: {
                color: "#FF7D00",
              },
            },
            expandAndCollapse: true,
            animationDuration: 550,
            animationDurationUpdate: 750,
          },
        ],
      };

      this.chartTree.setOption(treeOption);

      // 初始化柱状图
      this.chartBar = echarts.init(document.getElementById("barChart"));

      // 柱状图配置
      const barOption = {
        tooltip: {
          trigger: "axis",
          backgroundColor: "rgba(255, 255, 255, 0.9)",
          textStyle: { color: "#333" },
          axisPointer: {
            type: "shadow",
          },
        },
        grid: {
          left: "3%",
          right: "4%",
          bottom: "3%",
          containLabel: true,
        },
        xAxis: {
          type: "category",
          data: categoryBookCounts.map((item) => item.name),
          axisTick: {
            alignWithLabel: true,
          },
          axisLabel: {
            rotate: 45,
          },
        },
        yAxis: {
          type: "value",
          name: "数量",
          splitLine: {
            lineStyle: {
              type: "dashed",
            },
          },
        },
        series: [
          {
            name: "图书数量",
            type: "bar",
            data: categoryBookCounts.map((item) => item.bookCount),
            itemStyle: {
              color: "#409EFF",
            },
            label: {
              show: true,
              position: "top",
              color: "#333",
            },
          },
        ],
      };

      this.chartBar.setOption(barOption);

      // 监听窗口大小变化，调整图表
      window.addEventListener("resize", () => {
        this.chartTree.resize();
        this.chartBar.resize();
      });
    });
  },
  beforeUnmount() {
    // 修复图表实例销毁逻辑
    if (this.chartTree) {
      this.chartTree.dispose();
    }
    if (this.chartBar) {
      this.chartBar.dispose();
    }
  },
};
</script>
<style scoped>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  background: #f0f2f5;
  font-family: "Segoe UI", "Microsoft Yahei", sans-serif;
  color: #333;
}

.box {
  display: flex;
  min-height: 100vh;
  width: 1200px;
  background: linear-gradient(to right, #f8f9fa 0%, #e9ecef 100%);
  margin-left: 90px;
}

.box-right {
  margin-left: 240px;
  width: calc(100% - 240px);
  padding: 24px;
  transition: all 0.3s ease;
  background-color: #f9fafb;
}

.box-right-nav {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 20px;
}

.box-right-title {
  margin-bottom: 20px;
}

.box-right-title h2 {
  font-size: 24px;
  color: #333;
}

.box-right-title p {
  color: #666;
  margin-top: 8px;
}

.top {
  display: flex;
  justify-content: space-between;
  margin-bottom: 20px;
}

/* 按钮组样式优化 */
.top-left {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

.top-left .el-button {
  margin-right: 10px;
  border-radius: 8px;
  padding: 10px 16px;
  font-weight: 500;
  transition: all 0.3s ease;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}

.top-left .el-button--primary {
  background: linear-gradient(135deg, #409eff 0%, #337ecc 100%);
  border-color: #409eff;
  color: #ffffff;
}

.top-left .el-button--primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 14px rgba(64, 158, 255, 0.4);
}

/* 搜索区域优化 */
.top-right {
  display: flex;
  gap: 16px;
  align-items: center;
  flex-wrap: wrap;
}

.top-right .el-input {
  width: 200px;
  transition: all 0.3s ease;
}

.top-right .el-input__inner {
  border-radius: 8px;
  border: 1px solid #dcdfe6;
  padding: 10px 15px;
  transition: all 0.3s ease;
}

.top-right .el-input__inner:focus {
  border-color: #409eff;
  box-shadow: 0 0 8px rgba(64, 158, 255, 0.2);
}

.top-right .el-select {
  margin-right: 10px;
}

/* 二级分类选择器样式 */
.el-select .el-select {
  border: none;
  margin-right: 0;
}

.el-select .el-select .el-input__inner {
  padding: 0;
  border: none;
  background: transparent;
}
/* 响应式适配 */
@media (max-width: 1024px) {
  .box-left {
    width: 200px;
  }
  .box-right {
    margin-left: 200px;
    padding: 16px;
  }
}
@media (max-width: 768px) {
  .box {
    flex-direction: column;
  }
  .box-left {
    position: relative;
    width: 100%;
    height: auto;
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .box-right {
    margin-left: 0;
    width: 100%;
  }
  .top {
    flex-direction: column;
    align-items: stretch;
  }
}

.main {
  background-color: #fff;
  padding: 24px;
  border-radius: 12px;
  box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.05);
  margin-bottom: 24px;
  border: 1px solid #e4e6eb;
  /* min-height: 300px; */
}

.el-table {
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid #ebeef5;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
}

/* 图表区域优化 */
.button {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: 20px 0;
}
.chart-box {
  background-color: #ffffff;
  border-radius: 12px;
  padding: 20px;
  flex: 1 1 45%;
  min-width: 320px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.05);
  transition: transform 0.3s ease;
  border: 1px solid #e4e6eb;
}
.chart-box:hover {
  transform: translateY(-5px);
}
.chart-box h3 {
  margin-bottom: 16px;
  font-size: 18px;
  color: #333;
}
#treeChart,
#barChart {
  flex: 1;
  min-height: 360px;
}
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 178px;
  height: 178px;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  line-height: 178px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
  object-fit: cover;
}
</style>